# Network utility functions

def stringToIntArray(buf):
    '''Return binary string as array of ints'''
    return [ord(x) for x in buf]

# same as binascii.unhexlify()
def hexToString(x):
    '''Returns a hex-encoded string x as a raw binary string.
    ex. hexToString('0aff000005') -> '\x0a\xff\x00\x00\x05' '''
    return ''.join([chr(int(x[i:i+2], 16)) for i in range(0, len(x), 2)])

def printableStr(s):
    '''Returns s with all the non-printing characters replaced by '.' '''
    return ''.join([ord(c) in range(32, 127) and c or '.' for c in s])

def printableChr(c):
    if ord(c) in range(32, 127):
        return c
    return '.'

# same as binascii.hexlify()
def hexDump(s):
    '''Returns binary string as hex-encoded string'''
    return ''.join(['%02x' % ord(c) for c in s])

def stringDump(s):
    '''Return binary string as addr/hexdump/ascii string'''
    DUMP_WIDTH = 8
    rows = []
    for j in range(0, len(s), DUMP_WIDTH):
        z = s[j:j+DUMP_WIDTH]
        row = '%04x   ' % j
        row += ' '.join(['%02x' % ord(i) for i in z] + ['  '] * (DUMP_WIDTH - len(z)))
        row += '   '
        row += ''.join([printableChr(x) for x in z])
        rows.append(row)
    return '\n'.join(rows)

def recvall(conn, numBytes):
    '''Receive exactly numBytes from socket connection,
    (unless connection is closed)'''
    data = ""
    newData = "."
    while len(data) < numBytes and len(newData) > 0:
        newData = conn.recv(numBytes - len(data))
        data += newData
    return data
